package com.itheima.user.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.behaviour.dto.FollowBehaviorDto;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.constants.SystemConstants;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.AppJwtUtil;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.user.dto.LoginDto;
import com.itheima.user.dto.UserRelationDto;
import com.itheima.user.mapper.ApUserFanMapper;
import com.itheima.user.mapper.ApUserFollowMapper;
import com.itheima.user.mapper.ApUserMapper;
import com.itheima.user.pojo.ApUser;
import com.itheima.user.pojo.ApUserFan;
import com.itheima.user.pojo.ApUserFollow;
import com.itheima.user.service.ApUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @description <p>APP用户信息 业务实现</p>
 *
 * @version 1.0
 * @package com.itheima.user.service.impl
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {

    @Autowired
    private ApUserFollowMapper apUserFollowMapper;

    @Autowired
    private ApUserFanMapper apUserFanMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * app端用户登录校验
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> loginCheck(LoginDto dto) {
        //1. 参数校验
        if(null == dto){
            throw new LeadNewsException(HttpCodeEnum.PARAM_REQUIRE);
        }
        Map<String,Object> resultMap = new HashMap<>();
        //2. 判断是否是匿名
        Long loginUserId = 0l;////3. 是匿名 默认的用户id为0, 生成token返回
        Map<String,Object> map = new HashMap<>();
        if(StringUtils.isNotEmpty(dto.getPhone()) && StringUtils.isNotEmpty(dto.getPassword())){
            //4. 不是匿名，则要通过手机号码校验，密码
            ApUser loginUser = query().eq("phone", dto.getPhone()).one();
            if(null == loginUser){
                throw new LeadNewsException("手机号码或密码错误");
            }
            //密码
            String encryptedPwd = DigestUtils.md5DigestAsHex((dto.getPassword() + loginUser.getSalt()).getBytes());
            if(!loginUser.getPassword().equals(encryptedPwd)){
                // 密码不一致
                throw new LeadNewsException("手机号码或密码错误");
            }
            loginUserId = loginUser.getId().longValue();
            loginUser.setSalt(null);
            loginUser.setPassword(null);
            resultMap.put("user", loginUser);
            map.put(SystemConstants.LOGIN_USER_IMAGE, loginUser.getImage());
            map.put(SystemConstants.LOGIN_USER_NAME,loginUser.getName());
        }
        //5. 校验通过后，生成token，返回user信息(密码、盐为空)
        map.put("id", loginUserId);
        String token = AppJwtUtil.createToken(map);
        resultMap.put("token",token);
        return resultMap;
    }

    /**
     * 关注作者与取消关注
     *
     * @param dto
     */
    @Override
    @Transactional
    public void userFollow(UserRelationDto dto) {
        //1. 判断当前用户是否是匿名用户
        if (RequestContextUtil.isAnonymous()) {
            // 需要登录后才能操作
            throw new LeadNewsException(HttpCodeEnum.NEED_LOGIN);
        }
        //2. 操作类型
        Integer operation = dto.getOperation();
        //3. 获取登录用户id
        int loginUserId = Integer.parseInt(RequestContextUtil.getLoginUserId());
        //4. 获取作者id
        Integer authorId = dto.getAuthorId();
        //5. 判断操作类型
        if(operation == 0){
            //5.1 取消关注
            // 删除关注记录
            removeFollow(loginUserId,authorId);
            // 删除粉丝记录
            removeFans(authorId,loginUserId);
        }else{
            //5.2 添加关注与粉丝
            // 判断是否关注过了，构建查询条件
            LambdaQueryWrapper<ApUserFollow> queryWrapper = Wrappers.<ApUserFollow>lambdaQuery()
                    .eq(ApUserFollow::getUserId, loginUserId)
                    .eq(ApUserFollow::getFollowId, authorId);
            ApUserFollow apUserFollow = apUserFollowMapper.selectOne(queryWrapper);
            if(null != apUserFollow){
                // 关注过了
                throw new LeadNewsException("已经关注过了!");
            }
            // 没关注过，
            // 查询登录用户信息
            ApUser loginUser = getById(loginUserId);
            // 查询作者信息
            ApUser author = getById(authorId);
            // 添加关注
            addFollow(loginUserId, author);
            // 添加粉丝
            addFans(authorId,loginUser);

            // 构建用户行为dto
            FollowBehaviorDto behaviorDto = new FollowBehaviorDto();
            // 被关注者 用户的id
            behaviorDto.setFollowId(authorId);
            // 文章
            behaviorDto.setArticleId(dto.getArticleId());
            // 关注者 用户的ID
            behaviorDto.setUserId(loginUserId);

            // 发送消息到Kafka
            kafkaTemplate.send(BusinessConstants.MqConstants.FOLLOW_BEHAVIOR_TOPIC, JSON.toJSONString(behaviorDto));
        }
    }

    /**
     * 添加粉丝
     * @param authorId
     * @param loginUser
     */
    private void addFans(Integer authorId, ApUser loginUser) {
        ApUserFan fans = new ApUserFan();
        fans.setUserId(authorId);
        fans.setFansId(loginUser.getId());
        fans.setFansName(loginUser.getName());
        fans.setLevel(0);
        fans.setCreatedTime(LocalDateTime.now());
        fans.setIsDisplay(1);
        fans.setIsShieldComment(0);
        fans.setIsShieldLetter(0);
        apUserFanMapper.insert(fans);
    }

    /**
     * 添加关注
     * @param loginUserId
     * @param author
     */
    private void addFollow(int loginUserId, ApUser author) {
        ApUserFollow follow = new ApUserFollow();
        follow.setUserId(loginUserId);
        follow.setFollowId(author.getId());
        follow.setFollowName(author.getName());
        follow.setLevel(1);// 一般
        follow.setIsNotice(1); // 要通知
        follow.setCreatedTime(LocalDateTime.now());
        apUserFollowMapper.insert(follow);
    }

    /**
     * 删除关注关系
     * @param userId
     * @param followerId
     */
    private void removeFollow(int userId, int followerId){
        LambdaQueryWrapper<ApUserFollow> queryWrapper = Wrappers.<ApUserFollow>lambdaQuery()
                .eq(ApUserFollow::getUserId, userId)
                .eq(ApUserFollow::getFollowId, followerId);
        apUserFollowMapper.delete(queryWrapper);
    }

    /**
     * 删除粉丝关系
     * @param userId
     * @param fansId
     */
    private void removeFans(int userId, int fansId){
        LambdaQueryWrapper<ApUserFan> queryWrapper = Wrappers.<ApUserFan>lambdaQuery()
                .eq(ApUserFan::getUserId, userId)
                .eq(ApUserFan::getFansId, fansId);
        apUserFanMapper.delete(queryWrapper);
    }

}
